package org.shj.springcloud.movie.controller;

import org.shj.springcloud.movie.pojo.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import feign.hystrix.FallbackFactory;

/* 方法一： 使用 fallback, 需要定义下面的 FeignClientFallback
@FeignClient(name = "microservice-provider-user", fallback = FeignClientFallback.class)
*/
/* 方法二： 使用 fallbackFactory, 可以获得 fallback 的原因 */
@FeignClient(name = "microservice-provider-user", fallbackFactory = FeignClientFallbackFactory.class)
/* 禁用自动包装 Hytrix  */
//@FeignClient(name = "microservice-provider-user", configuration = FeignDisableHytrixConf.class)
public interface UserFeignClient {

	/* Spring 提供的注解 */
	@RequestMapping(value = "/{id}", method = RequestMethod.GET)
	public User findById(@PathVariable("id") String id);

}

/*@Component
class FeignClientFallback implements UserFeignClient {
	public User findById(String id) {
		User user = new User();
		user.setId("Default ID1");
		user.setUsername("Default User1");
		user.setEmail("Default Email11");
		return user;
	}
}*/

@Component
class FeignClientFallbackFactory implements FallbackFactory<UserFeignClient>{
	private static final Logger log = LoggerFactory.getLogger(FeignClientFallbackFactory.class);
	
	//在某个时间窗口中， cause 有时为会 null，因此调用 cause 的方法有可能会抛出 NullpointException 异常。这是 Feign9.3 
	// 的 bug， 在 Feign9.4 中已经被解决
	public UserFeignClient create(Throwable cause){
		return new UserFeignClient(){
			public User findById(String id) {
				FeignClientFallbackFactory.log.info("=================== ");
				FeignClientFallbackFactory.log.info("fallback; reason is: ", cause);
				//cause.printStackTrace();
				User user = new User();
				user.setId("Default ID 22");
				user.setUsername("Default User222");
				user.setEmail("Default Email 222");
				return user;
			}
		};
	}
}
